home *** CD-ROM | disk | FTP | other *** search
- /*
- * varlena.c --
- * Functions for the variable-length built-in types.
- *
- * $Header: /private/postgres/src/utils/adt/RCS/varlena.c,v 1.17 1992/08/25 17:47:38 mer Exp $
- */
-
- #include <ctype.h>
- #include <strings.h>
-
- #include "tmp/postgres.h"
- #include "utils/log.h"
- #include "utils/palloc.h"
- #include "utils/builtins.h"
- struct varlena *shove_bytes ARGS((unsigned char *stuff , int len ));
-
- /* ========== USER I/O ROUTINES ========== */
-
-
- #define VAL(CH) ((CH) - '0')
- #define DIG(VAL) ((VAL) + '0')
-
- /*
- * byteain - converts from printable representation of byte array
- *
- * Non-printable characters must be passed as '\nnn' (octal) and are
- * converted to internal form. '\' must be passed as '\\'.
- * elog(WARN, ...) if bad form.
- *
- * BUGS:
- * The input is scaned twice.
- * The error checking of input is minimal.
- */
- struct varlena *
- byteain(inputText)
- char *inputText;
- {
- register char *tp;
- register char *rp;
- register int byte;
- struct varlena *result;
-
- if (inputText == NULL)
- elog(WARN, "Bad input string for type bytea");
-
- for (byte = 0, tp = inputText; *tp != '\0'; byte++)
- if (*tp++ == '\\')
- {
- if (*tp == '\\')
- tp++;
- else if (!isdigit(*tp++) ||
- !isdigit(*tp++) ||
- !isdigit(*tp++))
- elog(WARN, "Bad input string for type bytea");
- }
- tp = inputText;
- byte += sizeof(int32); /* varlena? */
- result = (struct varlena *) palloc(byte);
- result->vl_len = byte; /* varlena? */
- rp = result->vl_dat;
- while (*tp != '\0')
- if (*tp != '\\' || *++tp == '\\')
- *rp++ = *tp++;
- else {
- byte = VAL(*tp++);
- byte <<= 3;
- byte += VAL(*tp++);
- byte <<= 3;
- *rp++ = byte + VAL(*tp++);
- }
- return(result);
- }
-
- /*
- * Shoves a bunch of memory pointed at by bytes into varlena.
- * BUGS: Extremely unportable as things shoved can be string
- * representations of structs, etc.
- */
-
- struct varlena *
- shove_bytes(stuff, len)
-
- unsigned char *stuff;
- int len;
-
- {
- struct varlena *result;
-
- result = (struct varlena *) palloc(len + sizeof(int32));
- result->vl_len = len;
- bcopy(stuff + sizeof(int32), result->vl_dat, len - sizeof(int32));
- return(result);
- }
-
-
-
- /*
- * byteaout - converts to printable representation of byte array
- *
- * Non-printable characters are inserted as '\nnn' (octal) and '\' as
- * '\\'.
- *
- * NULL vlena should be an error--returning string with NULL for now.
- */
- char *
- byteaout(vlena)
- struct varlena *vlena;
- {
- register char *vp;
- register char *rp;
- register int val; /* holds unprintable chars */
- int i;
- int len;
- static char *result;
-
- if (vlena == NULL) {
- result = (char *) palloc(2);
- result[0] = '-';
- result[1] = '\0';
- return(result);
- }
- vp = vlena->vl_dat;
- len = 1; /* empty string has 1 char */
- for (i = vlena->vl_len - sizeof(int32); i != 0; i--) /* varlena? */
- if (*vp == '\\')
- len += 2;
- else if (isascii(*vp) && isprint(*vp))
- len++;
- else
- len += 4;
- rp = result = (char *) palloc(len);
- vp = vlena->vl_dat;
- for (i = vlena->vl_len - sizeof(int32); i != 0; i--) /* varlena? */
- if (*vp == '\\') {
- *vp++;
- *rp++ = '\\';
- *rp++ = '\\';
- } else if (isascii(*vp) && isprint(*vp))
- *rp++ = *vp++;
- else {
- val = *vp++;
- *rp = '\\';
- rp += 3;
- *rp-- = DIG(val & 07);
- val >>= 3;
- *rp-- = DIG(val & 07);
- val >>= 3;
- *rp = DIG(val & 03);
- rp += 3;
- }
- *rp = '\0';
- return(result);
- }
-
-
- /*
- * textin - converts "..." to internal representation
- */
- struct varlena *
- textin(inputText)
- char *inputText;
- {
- register struct varlena *result;
- register int len;
- extern bcopy();
-
- if (inputText == NULL)
- return(NULL);
- len = strlen(inputText) + sizeof(int32); /* varlena? */
- result = (struct varlena *) palloc(len);
- result->vl_len = len;
- bcopy(inputText, result->vl_dat, len - sizeof(int32)); /* varlena? */
- return(result);
- }
-
- /*
- * textout - converts internal representation to "..."
- */
- char *
- textout(vlena)
- struct varlena *vlena;
- {
- register int len;
- char *result;
- extern bcopy();
-
- if (vlena == NULL) {
- result = (char *) palloc(2);
- result[0] = '-';
- result[1] = '\0';
- return(result);
- }
- len = vlena->vl_len - sizeof(int32); /* varlena? */
- result = (char *) palloc(len + 1);
- bcopy(vlena->vl_dat, result, len);
- result[len] = '\0';
- return(result);
- }
-
-
- /* ========== PUBLIC ROUTINES ========== */
-
-
- /*
- * texteq - returns 1 iff arguments are equal
- * textne - returns 1 iff arguments are not equal
- */
- int32
- texteq(arg1, arg2)
- struct varlena *arg1, *arg2;
- {
- register int len;
- register char *a1p, *a2p;
-
- if (arg1 == NULL || arg2 == NULL)
- return((int32) NULL);
- if ((len = arg1->vl_len) != arg2->vl_len)
- return((int32) 0);
- a1p = arg1->vl_dat;
- a2p = arg2->vl_dat;
- /*
- * Varlenas are stored as the total size (data + size variable)
- * followed by the data. The size variable is an int32 so the
- * length of the data is the total length less sizeof(int32)
- */
- len -= sizeof(int32);
- while (len-- != 0)
- if (*a1p++ != *a2p++)
- return((int32) 0);
- return((int32) 1);
- }
-
- int32
- textne(arg1, arg2)
- struct varlena *arg1, *arg2;
- {
- return((int32) !texteq(arg1, arg2));
- }
-
- int32
- text_lt(arg1, arg2)
- struct varlena *arg1, *arg2;
- {
- int len;
- char *a1p, *a2p;
-
- if (arg1 == NULL || arg2 == NULL)
- return((int32) 0);
-
- a1p = VARDATA(arg1);
- a2p = VARDATA(arg2);
-
- if ((len = arg1->vl_len) > arg2->vl_len)
- len = arg2->vl_len;
- len -= sizeof(int32);
-
- while (len != 0 && *a1p == *a2p)
- {
- a1p++;
- a2p++;
- len--;
- }
- if (len)
- return (int32) (*a1p < *a2p);
- else
- return (int32) (arg1->vl_len < arg2->vl_len);
- }
-
- int32
- text_le(arg1, arg2)
- struct varlena *arg1, *arg2;
- {
- int len;
- char *a1p, *a2p;
-
- if (arg1 == NULL || arg2 == NULL)
- return((int32) 0);
-
- a1p = VARDATA(arg1);
- a2p = VARDATA(arg2);
-
- if ((len = arg1->vl_len) > arg2->vl_len)
- len = arg2->vl_len;
- len -= sizeof(int32); /* varlena! */
-
- while (len != 0 && *a1p == *a2p)
- {
- a1p++;
- a2p++;
- len--;
- }
- if (len)
- return (int32) (*a1p < *a2p);
- else
- return ((int32) VARSIZE(arg1) <= VARSIZE(arg2));
- }
-
- int32
- text_gt(arg1, arg2)
- struct varlena *arg1, *arg2;
- {
- return ((int32) !text_le(arg1, arg2));
- }
-
- int32
- text_ge(arg1, arg2)
- struct varlena *arg1, *arg2;
- {
- return ((int32) !text_lt(arg1, arg2));
- }
-
- /*-------------------------------------------------------------
- * byteaGetSize
- *
- * get the number of bytes contained in an instance of type 'bytea'
- *-------------------------------------------------------------
- */
- int32
- byteaGetSize(v)
- struct varlena *v;
- {
- register int len;
-
- len = v->vl_len - sizeof(v->vl_len);
-
- return(len);
- }
-
- /*-------------------------------------------------------------
- * byteaGetByte
- *
- * this routine treats "bytea" as an array of bytes.
- * It returns the Nth byte (a number between 0 and 255) or
- * it dies if the length of this array is less than n.
- *-------------------------------------------------------------
- */
- int32
- byteaGetByte(v, n)
- struct varlena *v;
- int32 n;
- {
- int len;
- int byte;
-
- len = byteaGetSize(v);
-
- if (n>=len) {
- elog(WARN, "byteaGetByte: index (=%d) out of range [0..%d]",
- n,len-1);
- }
-
- byte = (unsigned char) (v->vl_dat[n]);
-
- return((int32) byte);
- }
-
- /*-------------------------------------------------------------
- * byteaGetBit
- *
- * This routine treats a "bytea" type like an array of bits.
- * It returns the value of the Nth bit (0 or 1).
- * If 'n' is out of range, it dies!
- *
- *-------------------------------------------------------------
- */
- int32
- byteaGetBit(v, n)
- struct varlena *v;
- int32 n;
- {
- int len;
- int byteNo, bitNo;
- int byte;
-
- byteNo = n/8;
- bitNo = n%8;
-
- byte = byteaGetByte(v, byteNo);
-
- if (byte & (1<<bitNo)) {
- return((int32)1);
- } else {
- return((int32)0);
- }
- }
- /*-------------------------------------------------------------
- * byteaSetByte
- *
- * Given an instance of type 'bytea' creates a new one with
- * the Nth byte set to the given value.
- *
- *-------------------------------------------------------------
- */
-
- struct varlena *
- byteaSetByte(v, n, newByte)
- struct varlena *v;
- int32 n;
- int32 newByte;
- {
- int len;
- struct varlena *res;
- int i;
-
- len = byteaGetSize(v);
-
- if (n>=len) {
- elog(WARN,
- "byteaSetByte: index (=%d) out of range [0..%d]",
- n, len-1);
- }
-
- /*
- * Make a copy of the original varlena.
- */
- res = (struct varlena *) palloc(VARSIZE(v));
- if (res==NULL) {
- elog(WARN, "byteaSetByte: Out of memory (%d bytes requested)",
- VARSIZE(v));
- }
- bcopy((char *)v, (char *)res, VARSIZE(v));
-
- /*
- * Now set the byte.
- */
- res->vl_dat[n] = newByte;
-
- return(res);
- }
-
- /*-------------------------------------------------------------
- * byteaSetBit
- *
- * Given an instance of type 'bytea' creates a new one with
- * the Nth bit set to the given value.
- *
- *-------------------------------------------------------------
- */
-
- struct varlena *
- byteaSetBit(v, n, newBit)
- struct varlena *v;
- int32 n;
- int32 newBit;
- {
- struct varlena *res;
- int oldByte, newByte;
- int byteNo, bitNo;
-
- /*
- * sanity check!
- */
- if (newBit != 0 && newBit != 1) {
- elog(WARN, "byteaSetByte: new bit must be 0 or 1");
- }
-
- /*
- * get the byte where the bit we want is stored.
- */
- byteNo = n / 8;
- bitNo = n % 8;
- oldByte = byteaGetByte(v, byteNo);
-
- /*
- * calculate the new value for that byte
- */
- if (newBit == 0) {
- newByte = oldByte & (~(1<<bitNo));
- } else {
- newByte = oldByte | (1<<bitNo);
- }
-
- /*
- * NOTE: 'byteaSetByte' creates a copy of 'v' & sets the byte.
- */
- res = byteaSetByte(v, byteNo, newByte);
-
- return(res);
- }
-